%{
	#include <stdio.h>
	#include <assert.h>
	#include "../model/datatypes.h"
	#include "../model/model.h"
	#include "../model/limits.h"
	
	#define YYSTYPE Expression

	char* yytext;
	int yylex(void);
	int yylineno;
	void yyerror(char *);
	extern FILE *yyin;
	extern TBox* tbox;

	// for parsing conjunction
	int cls_exp_count;      				/* number of conjuncts */
	Concept* cls_exps[MAX_CONJUNCT_COUNT];	/* conjuncts */


%}

%start ontologyDocument

%token IRI_REF PNAME_NS
%token PREFIX ONTOLOGY IMPORT
%token CLASS OBJECT_PROPERTY
%token OBJECT_INTERSECTION_OF OBJECT_SOME_VALUES_FROM 
%token SUB_CLASS_OF EQUIVALENT_CLASSES 
%token SUB_OBJECT_PROPERTY_OF TRANSITIVE_OBJECT_PROPERTY

%%

ontologyDocument:
	prefixDeclaration ontology
	;

prefixDeclaration:
	| prefixDeclaration PREFIX '(' prefixName '=' fullIRI ')'
	;

prefixName:
	PNAME_NS
	;

fullIRI:
	IRI_REF
	;
	
ontology:
	ONTOLOGY '(' ontologyIRI versionIRI axioms ')' 
	| ONTOLOGY '(' ontologyIRI axioms ')' 
	;

ontologyIRI:
	IRI
	;

versionIRI:
	IRI
	;

IRI:
	/* fullIRI | abbreviatedIRI */
	fullIRI
	;

/*
abbreviatedIRI:
	PNAME_LN
	;
*/
	
axioms:
	| axioms axiom
	;

axiom:
	classAxiom 
	;

classAxiom:
	subClassOf | equivalentClasses
	;

subClassOf:
	SUB_CLASS_OF '(' classExpression classExpression ')' {
		add_subclass_axiom(create_subclass_axiom($3.concept,$4.concept), tbox);
	}
	;

equivalentClasses:
	EQUIVALENT_CLASSES '(' classExpression classExpression ')' {
		add_eqclass_axiom(create_eqclass_axiom($3.concept,$4.concept), tbox);
	}
	;

classExpression:
	class | objectIntersectionOf | objectSomeValuesFrom
	;

class:
	IRI	{ $$.concept = get_create_atomic_concept(yytext,tbox); }
	/* TODO: here OWL_THING, OWL_NOTHING */
	;

objectIntersectionOf:
	OBJECT_INTERSECTION_OF '(' classExpression classExpression classExpressions ')' {
		cls_exps[cls_exp_count++] = $3.concept;
		cls_exps[cls_exp_count++] = $4.concept;
		$$.concept = get_create_conjunction(cls_exp_count, cls_exps, tbox);
		cls_exp_count = 0;
	}
	;

classExpressions:
	| classExpression classExpressions {
		if ($1.concept != NULL)
			cls_exps[cls_exp_count++] = $1.concept;
	}
	;

objectSomeValuesFrom:
	OBJECT_SOME_VALUES_FROM '(' objectPropertyExpression classExpression ')' {
		$$.concept = get_create_exists_restriction($3.role,$4.concept, tbox);
	}
	;

objectPropertyExpression:
	objectProperty
	;

objectProperty:
	IRI	{ $$.role = get_create_atomic_role(yytext, tbox); }
	;

%%

void yyerror(char *s) {
	fprintf(stderr, "\nline %d: %s\n", yylineno, s);
}
